﻿using Common.MQ;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Common.RabbitMQ
{
    /// <summary>
    /// 消息队列构建者
    /// </summary>
    public class RabbitBuilder : IMessageQueueBuilder
    {
        private readonly IServiceCollection services;
        /// <summary>
        /// 消息队列构建者
        /// </summary>
        /// <param name="config"></param>
        /// <param name="services"></param>
        public RabbitBuilder(RabbitConfig config, IServiceCollection services)
        {
            this.Config = config;
            this.services = services;
        }
        internal readonly List<QueueSpec> ProducerQueues = new List<QueueSpec>();
        internal readonly List<QueueSpec> ConsumerQueues = new List<QueueSpec>();
        internal readonly Dictionary<QueueSpec, IMessageHandler[]> ConsumerHandlers = new Dictionary<QueueSpec, IMessageHandler[]>();
        internal IMQProducer Producer { get; private set; }
        internal List<MQConsumerBase> Consumers { get; private set; } = new List<MQConsumerBase>();
        /// <summary>
        /// 配置项
        /// </summary>
        public RabbitConfig Config { get; set; }
        /// <summary>
        /// 添加消费者
        /// </summary>
        /// <param name="queue"></param>
        /// <param name="handlers"></param>
        /// <returns></returns>
        public RabbitBuilder AddConsumer(QueueSpec queue, params IMessageHandler[] handlers)
        {
            NewConsumer(queue, handlers);
            return this;
        }
        /// <summary>
        /// 添加生产者
        /// </summary>
        /// <param name="queue"></param>
        /// <returns></returns>
        public RabbitBuilder AddProducer(QueueSpec queue)
        {
            NewProducer(queue);
            return this;
        }
        /// <inheritdoc/>
        public IMessageQueueProvider Build()
        {
            IMessageQueueProvider provider = new RabbitProvider(this);
            this.services.AddSingleton(provider);
            return provider;
        }

        IMessageQueueBuilder IMessageQueueBuilder.AddConsumer(IDestination dest, params IMessageHandler[] handlers)
        {
            NewConsumer(dest, handlers);
            return this;
        }

        IMessageQueueBuilder IMessageQueueBuilder.AddProducer(IDestination dest)
        {
            NewProducer(dest);
            return this;
        }

        private void NewConsumer(IDestination dest, params IMessageHandler[] handlers)
        {
            var queue = dest as QueueSpec;
            if (queue == null)
            {
                throw new ArgumentException("dest参数有误");
            }
            if (handlers == null || !handlers.Any())
            {
                throw new ArgumentException("至少需要指定一个消息处理程序");
            }
            List<IMessageHandler> list = new List<IMessageHandler>();
            foreach (var item in handlers)
            {
                var typeOfT = item.GetType();
                if (list.Any(x => x.GetType() == typeOfT))
                {
                    throw new ApplicationException("不能添加重复的消息处理程序");
                }
                list.Add(item);
            }
            ConsumerQueues.Add(queue);
            ConsumerHandlers.Add(queue, handlers);
            var Consumer = new RabbitConsumer(Config, queue, list.ToArray());
            Consumer.Start();
            Consumers.Add(Consumer);
        }

        private void NewProducer(IDestination dest)
        {
            var queue = dest as QueueSpec;
            if (queue == null)
            {
                throw new ArgumentException("dest参数有误");
            }
            if (Producer == null)
            {
                Producer = new RabbitProducer(Config, queue);
                this.services?.AddSingleton<IMQProducer>(Producer);
            }
            else
            {
                Producer.Declare(queue);
            }
            ProducerQueues.Add(queue);
        }
    }
}
